package app.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONNull;

public class ClassUtil {
	
	/**
	 * 将list中的map key命名改成驼峰规则
	 * @param list
	 * @return
	 */
	public static List<Map<String, Object>> toHumpNamed(List<Map<String, Object>> list) {
		if ((list == null) || (list.size() == 0)) {
			return new ArrayList<Map<String, Object>>();
		}

		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();

		for (Map<String, Object> map : list) {
			Map<String, Object> humpNamedMap = toHumpNamed(map);
			result.add(humpNamedMap);
		}

		return result;
	}

	/**
	 * 将map中 key命名改成驼峰规则
	 * @param map
	 * @return
	 */
	public static Map<String, Object> toHumpNamed(Map<String, Object> map) {
		if ((map == null) || (map.size() == 0)) {
			return new HashMap<String, Object>();
		}

		Map<String, Object> result = new HashMap<String, Object>();

		for (String key : map.keySet()) {
			Object value = map.get(key);
			result.put(toHumpNamed(key), value);
		}

		return result;
	}

	/**
	 * 修改成驼峰格式
	 * @param name
	 * @return
	 */
	public static String toHumpNamed(String name) {
		if (name == null) {
			return "";
		}
		String result = "";
		String[] names = name.split("_");
		for (int i = 0; i < names.length; i++) {
			if (i == 0)
				result = result + names[i].toLowerCase();
			else {
				result = result + firstUpperCaseOtherLower(names[i]);
			}
		}

		return result;
	}

	/**
	 * 将驼峰命名改成下划线命名
	 * @param name
	 * @return
	 */
	public static String reverseHumpNamed(String name) {
		if (name == null) {
			return "";
		}
		String result = "";
		for (int i = 0; i < name.length(); i++) {
			String currentChar = name.charAt(i) + "";

			if (currentChar.toUpperCase().equals(currentChar))
				result = result + "_" + currentChar;
			else {
				result = result + currentChar;
			}
		}

		return result;
	}

	private static String firstUpperCaseOtherLower(String name) {
		if ((name == null) || (name.length() < 1)) {
			return name;
		}

		byte[] items = name.toLowerCase().getBytes();
		items[0] = ((byte) ((char) items[0] - 'a' + 65));

		return new String(items);
	}
	
	
	/**
	 * mapToJavaBean
	 * @param objClass
	 * @param map
	 * @return
	 */
	public static <T> T mapToEntity(Class<T> objClass,Map<String,Object> map){
		T entity = null;
		try {
			entity = objClass.newInstance();
			BeanInfo beanInfo = Introspector.getBeanInfo(entity.getClass());  
	        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  

	        for (PropertyDescriptor property : propertyDescriptors) {  
	            String key = property.getName();  
	            if (map.containsKey(key)) {  
	                Object value = map.get(key);  
	                if(value instanceof JSONNull){
	                	value = null;
	                }
	                Object convertValue = value;
	                // 得到property对应的setter方法  
	                Method setter = property.getWriteMethod(); 
	                Class<?> propertyType = property.getPropertyType();
					if ((propertyType == Double.class) || (propertyType == Double.TYPE)) {
						if (!(value instanceof Double))
							convertValue = 0.0;
					} else if ((propertyType == Long.class) || (propertyType == Long.TYPE)) {
						if (!(value instanceof Long))
							convertValue = 0.0;
					} else if ((propertyType == Integer.class) || (propertyType == Integer.TYPE)) {
						if (!(value instanceof Integer))
							convertValue = 0;
					} else if ((propertyType == Float.class) || (propertyType == Float.TYPE)) {
						if (!(value instanceof Float))
							convertValue = 0.0;
					} else if ((propertyType == Boolean.TYPE) || (propertyType == Boolean.class)) {
						if (!(value instanceof Boolean)) {
							if (("1".equals(value)) || ("Y".equalsIgnoreCase(value + "")) || ("Yes".equalsIgnoreCase(value + "")))
								convertValue = true;
							else
								convertValue = false;
						}
					} else if (propertyType == Date.class) {
						if ((!(value instanceof Date)) && (value != null)) {
							convertValue = null;
						}
					}
					
					setter.invoke(entity, convertValue);  
	            }  
	        }
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IntrospectionException e) {
			e.printStackTrace();
		}
        return entity;
	}
	
	public static Object mapToObject(Map<String, Object> map, Class<?> beanClass){    
        if (map == null)   
            return null;    
  
        try {
        	Object obj = beanClass.newInstance();  
        	  
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());    
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();    
            for (PropertyDescriptor property : propertyDescriptors) {  
                Method setter = property.getWriteMethod();    
                if (setter != null) {  
                    setter.invoke(obj, map.get(property.getName()));   
                }  
            }  
            return obj;  
        }catch (Exception e) {
		}
        return null;
    }    
	
	public static Map<String, Object> entityToMap(Object obj){    
        if(obj == null)  
            return null;      
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());    
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();    
            for (PropertyDescriptor property : propertyDescriptors) {    
                String key = property.getName();    
                if (key.compareToIgnoreCase("class") == 0) {   
                    continue;  
                }  
                Method getter = property.getReadMethod();  
                Object value = getter!=null ? getter.invoke(obj) : null;  
                map.put(key, value);  
            }    
		} catch (Exception e) {
		}
        return map;  
    }    
	
	public static Map<String,Object> mergeTwoMap(Map<String,Object> mergeMap,Map<String,Object> mergedMap){
		for(String key:mergeMap.keySet()){
			mergedMap.put(key, mergeMap.get(key));
		}
		return mergedMap;
	}
	
//	public static Map<String, Object> entityToMap(Object obj) {    
//        if(obj == null){    
//            return null;    
//        }   
//  
//        Map<String, Object> map = new HashMap<String, Object>();    
//  
//        Field[] declaredFields = obj.getClass().getDeclaredFields();    
//        for (Field field : declaredFields) {    
//            field.setAccessible(true);  
//            try {
//				map.put(field.getName(), field.get(obj));
//			} catch (IllegalArgumentException e) {
//				e.printStackTrace();
//			} catch (IllegalAccessException e) {
//				e.printStackTrace();
//			}  
//        }    
//  
//        return map;  
//    }   
	
//	public static <T> T mapToObject(Class<T> clazz, Map<String, ?> map)
//	  {
//	    Object result = null;
//	    try {
//	      result = clazz.newInstance();
//	    } catch (InstantiationException e) {
//	      e.printStackTrace();
//	    } catch (IllegalAccessException e) {
//	      e.printStackTrace();
//	    }
//
//	    Field[] fields = ReflectionUtil.getDeclaredFields(clazz);
//	    for (Field field : fields)
//	    {
//	      if (Modifier.isStatic(field.getModifiers())) {
//	        continue;
//	      }
//
//	      if (field.isAnnotationPresent(XmlField.class)) {
//	        XmlField xmlField = (XmlField)field.getAnnotation(XmlField.class);
//	        String refer = xmlField.refer();
//	        if (!(StringUtil.isEmpty(refer))) {
//	          Object referValue = map.get(refer);
//	          if (referValue != null) {
//	            if (xmlField.spelling()) {
//	              referValue = ChineseSpelling.getSpelling(referValue + "");
//	            }
//	            if ((!(StringUtil.isEmpty(xmlField.prefix()))) && (map.get(xmlField.prefix()) != null)) {
//	              referValue = map.get(xmlField.prefix()) + "." + referValue;
//	            }
//	            ReflectionUtil.setFieldValue(result, field.getName(), referValue);
//	          }
//	        }
//	      }
//	      else
//	      {
//	        Object value = map.get(field.getName());
//	        if (value == null) {
//	          value = map.get(reverseHumpNamed(field.getName()));
//	          if (value == null) {
//	            continue;
//	          }
//	        }
//
//	        ReflectionUtil.setFieldValue(result, field.getName(), value);
//	      }
//	    }
//	    return (T) result;
//	  }
}